package cn.rjzjh.tapestry.busi.service.security;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.ioc.annotations.InjectService;
import org.apache.tapestry5.ioc.annotations.Symbol;
import org.hibernate.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.access.SecurityMetadataSource;
import org.springframework.security.access.method.MethodSecurityMetadataSource;
import org.springframework.security.web.FilterInvocation;
import org.springframework.stereotype.Service;

import cn.rjzjh.tapestry.busi.model.ca.CaRoleRes;
import cn.rjzjh.tapestry.component.services.ISupportedLocales;
import cn.rjzjh.tapestry.tams.services.base.IHbService;

@Service("CommonSecurityMetadataSource")
public class CommonSecurityMetadataSource implements SecurityMetadataSource,
		MethodSecurityMetadataSource {
	private final static Map<String, Collection<ConfigAttribute>> resourceMap = new HashMap<String, Collection<ConfigAttribute>>();
	public static volatile String UrlRegExp;// 地址匹配模式

	@Autowired
	@Inject
	private IHbService hbService;

	@Autowired
	@Inject
	private Session session;

	@Autowired
	@InjectService("locales")
	protected ISupportedLocales supportedLocales;

	/****
	 * 地址过滤查找权限
	 */
	@PostConstruct
	public void loadResourceDefine() {
		// 取得所有的资源
		List<CaRoleRes> allRoleRe = hbService.getQuery(
				"select  t from CaRoleRes t").list();// 以后加入操作类资源定义
		if (CollectionUtils.isNotEmpty(allRoleRe)) {
			for (CaRoleRes caRoleRes : allRoleRe) {
				String resValue = caRoleRes.getCaResource().getResValue();
				String roleIdStr = String
						.valueOf(caRoleRes.getCaRole().getId());
				if (resourceMap.get(resValue) == null) {// 没有此资源
					Collection<ConfigAttribute> atts = new ArrayList<ConfigAttribute>();
					ConfigAttribute ca = new SecurityConfig(roleIdStr);
					atts.add(ca);
					resourceMap.put(resValue, atts);
				} else {// 已有此资源
					ConfigAttribute ca = new SecurityConfig(roleIdStr);
					resourceMap.get(resValue).add(ca);
				}
			}
		}
	}

	@Override
	public Collection<ConfigAttribute> getAttributes(Object object)
			throws IllegalArgumentException {

		if (object instanceof FilterInvocation) {
			if (StringUtils.isBlank(UrlRegExp)) {
				String langs = supportedLocales.getSupportedLocales()
						.replaceAll(",", "|");
				UrlRegExp = "(\\/(" + langs + "))?%s(:)?\\w*";
			}
			String url = ((FilterInvocation) object).getRequestUrl();
			for (Iterator iterator = resourceMap.keySet().iterator(); iterator
					.hasNext();) {
				String resURL = (String) iterator.next();
				String urlReg = String.format(UrlRegExp, resURL);
				if (url.matches(urlReg)) {
					Collection<ConfigAttribute> returnCollection = resourceMap
							.get(resURL);
					return returnCollection;
				}
			}
		} else {
			System.out.println("不是地址");
		}
		return null;// 返回null代表不做检查，直接通过
	}

	@Override
	public Collection<ConfigAttribute> getAllConfigAttributes() {
		return null;
	}

	@Override
	public boolean supports(Class<?> clazz) {
		return true;
	}

	/****
	 * 方法过滤查找权限
	 */
	@Override
	public Collection<ConfigAttribute> getAttributes(Method method,
			Class<?> targetClass) {
		String className = targetClass.getName();
		String methodName = method.getName();
		if (StringUtils.isNotBlank(className)
				&& StringUtils.isNotBlank(methodName)) {
			String methodAllName = className + "." + methodName;
			if (resourceMap.get(methodAllName) != null) {
				return resourceMap.get(methodAllName);
			}
		}
		System.out.println(className + "." + methodName);
		return null;
	}

}
